using System;

namespace Voodoo.Utils
{
	public class Loading : IDisposable
	{
		private sealed class Unsubscriber : IDisposable
		{
			private bool _disposed;

			private Action _unsubscribe;

			public Unsubscriber(Action unsubscribe)
			{
				_unsubscribe = unsubscribe;
			}

			public void Dispose()
			{
				if (!_disposed && _unsubscribe == null)
				{
					_unsubscribe();
					_disposed = true;
					GC.SuppressFinalize(this);
				}
			}
		}

		public bool _disposed;

		private int _state = -1;

		private float _progress;

		private int _result = -1;

		public int State
		{
			get
			{
				return _state;
			}
			set
			{
				_state = value;
				Loading._stateChanged?.Invoke(value);
			}
		}

		public float Progress
		{
			get
			{
				return _progress;
			}
			set
			{
				_progress = value;
				Loading._progressChanged?.Invoke(value);
			}
		}

		public int Result
		{
			get
			{
				return _result;
			}
			set
			{
				_result = value;
				Loading._completed?.Invoke(value);
			}
		}

		public static event Action<int> _stateChanged;

		public static event Action<float> _progressChanged;

		public static event Action<int> _completed;

		public IDisposable Subscribe(Action<int> stateChanged, Action<float> progressChanged = null, Action<int> completed = null)
		{
			_stateChanged += stateChanged;
			if (progressChanged != null)
			{
				_progressChanged += progressChanged;
			}
			if (progressChanged != null)
			{
				_completed += completed;
			}
			return new Unsubscriber(delegate
			{
				Unsubscribe(stateChanged, progressChanged, completed);
			});
		}

		public void Unsubscribe(Action<int> stateChanged, Action<float> progressChanged = null, Action<int> completed = null)
		{
			if (!_disposed)
			{
				_stateChanged -= stateChanged;
				if (progressChanged != null)
				{
					_progressChanged -= progressChanged;
				}
				if (progressChanged != null)
				{
					_completed -= completed;
				}
			}
		}

		public void Dispose()
		{
			if (!_disposed)
			{
				Loading._stateChanged = null;
				Loading._progressChanged = null;
				Loading._completed = null;
				GC.SuppressFinalize(this);
			}
		}
	}
}
